package com.lixin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lixin.entity.Friendships;
import com.lixin.entity.Users;
import com.lixin.exception.DuplicateFriendRequestException;
import com.lixin.exception.UserNotFoundException;
import com.lixin.mapper.FriendshipsMapper;
import com.lixin.model.response.FindAllFriendsResponse;
import com.lixin.service.IFriendshipsService;
import com.lixin.service.IUsersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 用于存储用户之间的好友关系 服务实现类
 * </p>
 *
 * @author lixin
 * @since 2023-07-28
 */
@Service
@Slf4j
public class FriendshipsServiceImpl extends ServiceImpl<FriendshipsMapper, Friendships> implements IFriendshipsService {

    /**
     * 获取代理对象避免本类调用动态代理失效比如事务 缓存等注解 如果代理过多可以考虑把代理对象都抽取到一个类 目前先这样做
     *
     * @return
     */
    public IFriendshipsService getManager() {
        return (IFriendshipsService) AopContext.currentProxy();
    }

    @Autowired
    private IUsersService iUsersService;
    @Autowired
    private FriendshipsMapper friendshipsMapper;

    @Override
    public void addFriend(Integer friendId, Integer userId) {
        Users users = iUsersService.findById(friendId);
        if (users == null) {
            throw new UserNotFoundException();
        }
        if (isFriend(friendId, userId)) {
            throw new DuplicateFriendRequestException();
        }
        Friendships friendships = new Friendships();
        friendships.setUserId(userId);
        friendships.setFriendId(friendId);
        getManager().addOrUpdate(friendships);
    }

    /**
     * 其实这里应该有一些逻辑比如更新时间之类的操作 但是目前表设计的比较简单先不做了
     *
     * @param friendships
     * @return
     */
    @Override
    public Friendships addOrUpdate(Friendships friendships) {
        if (getManager().selectById(friendships.getFriendshipId()) == null) {
            friendshipsMapper.insert(friendships);
            return friendships;
        }
        //todo  update date
        friendshipsMapper.updateById(friendships);
        return friendships;
    }

    @Override
    public Boolean isFriend(Integer friendId, Integer userId) {
        return findFriendByFriendAndUserId(friendId, userId) != null;
    }

    @Override
    public Friendships findFriendByFriendAndUserId(Integer friendId, Integer userId) {
        return this.lambdaQuery().eq(Friendships::getFriendId, friendId).eq(Friendships::getUserId, userId).one();
    }

    /**
     * 这里盖一层主要是为了用缓存
     *
     * @param friendshipsId
     * @return
     */
    @Override
    public Friendships selectById(Integer friendshipsId) {
        if (friendshipsId == null) {
            return null;
        }
        return friendshipsMapper.selectById(friendshipsId);
    }

    @Override
    public Friendships builder(Date date, Integer userId, Integer friendId) {
        Friendships friendships = new Friendships();
        friendships.setTimestamp(date);
        friendships.setUserId(userId);
        friendships.setFriendId(friendId);
        return friendships;
    }

    @Override
    public Integer deleteFriend(Integer friendId, Integer userId) {
        log.info("deleteFriend friendId:{},userId:{}", friendId, userId);
        return friendshipsMapper.delete(this.lambdaQuery().eq(Friendships::getFriendId, friendId).eq(Friendships::getUserId, userId));
    }

    @Override
    public List<Users> findAllFriends(Integer userId) {
        List<Friendships> list = findAllFriendsQuery(userId);
        if (list.isEmpty()) {
            return new ArrayList<>();
        }
        return iUsersService.listByIds(list.stream().map(Friendships::getFriendId).toList());
    }
    @Override
    public List<Friendships> findAllFriendsQuery(Integer userId) {
        return this.lambdaQuery().select(Friendships::getFriendId).eq(Friendships::getUserId, userId).list();
    }

}
